// 文件名：mdspan_backend_agnostic.cpp
// 目的：实现与后端无关（布局/内存来源可变）的 Frobenius 范数计算，
//      通过概念（concept）约束让算法接受任意“元素为 double、秩为 2”的 mdspan 视图。
// 要点：
//   - 概念 rank2_mdspan：限制 element_type 为 double，且 rank()==2；
//   - frobenius_norm(View)：双重循环累加元素平方并开方；
//   - main 中构造固定 extents<2,3> 的 mdspan 作为演示，算法同样适用于 layout_left/stride/GPU 内存等。
// 注意：
//   - std::mdspan 默认 layout_right；可根据后端需要更换映射或 accessor；
//   - 视图不拥有数据，须保证底层 storage 生命周期。
// 复杂度：O(M*N)。
#include <concepts>
#include <iostream>
#include <mdspan>
#include <vector>

template <class MDSpan>
concept rank2_mdspan =
    std::same_as<typename MDSpan::element_type, double> &&
    (MDSpan::rank() == 2);

template <rank2_mdspan View>
double frobenius_norm(View view) {
    double sum = 0.0;
    for (std::size_t i = 0; i < view.extent(0); ++i) {
        for (std::size_t j = 0; j < view.extent(1); ++j) {
            double v = view(i, j);
            sum += v * v;
        }
    }
    return std::sqrt(sum);
}

int main() {
    std::vector<double> storage{1.0, 2.0, 3.0,
                                4.0, 5.0, 6.0};
    std::mdspan<double, std::extents<std::size_t, 2, 3>> mat(storage.data());
    std::cout << "||A||_F = " << frobenius_norm(mat) << '\n';

    // 同一算法可复用在其他布局/后端（如列主序、GPU 内存等）
    return 0;
}